package com.yociyy.auth.config;

import com.alibaba.nacos.client.identify.Base64;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import java.util.Arrays;

/**
 * 认证服务器配置
 * 
 * @author: YoCiyy
 * @date: 2020/6/1
 */
@Configuration
@EnableAuthorizationServer
@RequiredArgsConstructor
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

	/** 令牌持久化配置 */
	private final TokenStore tokenStore;
	/** 客户端详情服务 */
	private final ClientDetailsService clientDetailsService;
	/** 用户详情服务 */
	private final UserDetailsService userDetailsService;
	/** 认证管理器 */
	private final AuthenticationManager authenticationManager;
	/** 授权码服务 */
	private final AuthorizationCodeServices authorizationCodeServices;
	/** jwtToken解析器 */
	@Autowired(required = false)
	private JwtAccessTokenConverter jwtAccessTokenConverter;
	/** token增强器 */
	@Autowired(required = false)
	private TokenEnhancer tokenEnhancer;




	/**
	 * 配置客户端详情信息
	 * 
	 * @param clients 客户端对象
	 */
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		// 将客户端信息存储到数据库
		clients.withClientDetails(clientDetailsService);
	}

	/**
	 * 配置令牌管理服务
	 * 
	 * @return
	 */
//	@Bean
//	@Primary
//	public AuthorizationServerTokenServices tokenService() {
//		DefaultTokenServices service = new DefaultTokenServices();
//		service.setClientDetailsService(clientDetailsService);
//		service.setSupportRefreshToken(true);
//		service.setTokenStore(tokenStore);
//		// 令牌增强
//		TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
//		tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));
//		service.setTokenEnhancer(tokenEnhancerChain);
//		// 令牌默认有效期2小时
//		service.setAccessTokenValiditySeconds(7200);
//		// 刷新令牌默认有效期3天
//		service.setRefreshTokenValiditySeconds(259200);
//		return service;
//	}



	/**
	 * 配置令牌访问端点
	 * 
	 * @param endpoints 端点
	 */
	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
//		endpoints.authenticationManager(authenticationManager) // 认证管理器
//				.authorizationCodeServices(authorizationCodeServices) // 授权码服务
//				.userDetailsService(userDetailsService)
//				.tokenServices(tokenService()) // 令牌管理服务
//				.allowedTokenEndpointRequestMethods(HttpMethod.POST);
//

		endpoints
				// 令牌管理
				.tokenStore(tokenStore)
				// 认证管理器
				.authenticationManager(authenticationManager)
				// 授权码服务
				.authorizationCodeServices(authorizationCodeServices)
				// 用户详情服务 refresh_token需要userDetailsService
				.reuseRefreshTokens(false)
				.userDetailsService(userDetailsService)
				// 允许token端点的请求方式
				.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);

		// 令牌管理服务 yoci.security.oauth2.tokenStore.type=rsa-jwt-server 那么使用的是JWT
		if (jwtAccessTokenConverter != null && tokenEnhancer != null) {
			TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
			tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer, jwtAccessTokenConverter));
			endpoints.tokenEnhancer(tokenEnhancerChain);
		}
	}

	/**
	 * 配置安全约束
	 */
	@Override
	public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
		security
				// oauth/check_token公开
				.checkTokenAccess("permitAll()")
				// 表单认证（申请令牌）
				.allowFormAuthenticationForClients();
	}

	public static void main(String[] args) {
		System.out.println("client password " + new BCryptPasswordEncoder().encode("yoci"));
		System.out.println("client password " + new BCryptPasswordEncoder().encode("21232f297a57a5a743894a0e4a801fc3"));

		byte[] key = ("yoci:yoci").getBytes();
		String authKey = new String(Base64.encodeBase64(key));
		System.out.println("Authorization " + authKey);

		System.out.println("==============================================================================");
		String hashpw = BCrypt.hashpw("yoci", BCrypt.gensalt());
		System.out.println(hashpw);
	}

}
